import React, { useEffect, useState } from 'react';
import { Tree, Input } from 'antd';

import styles from './index.module.sass';

const { Search } = Input;

export interface TreeData {
    /**树节点标题 */
    name: string

    /**树节点的值 */
    value: string

    /**当前树节点的子节点 */
    children?: TreeData[]

    /**节点是否可选择 */
    selectable?: boolean
}

interface Props {
    /**后端数据请求函数 */
    remote: Function

    /**搜索框的提示信息 */
    placeholder?: string

    /**树节点的触发事件 */
    onSelect?: Function

    /**禁用父节点选择 */
    isDisableSelect?: boolean

    /**初始化时展开的树节点 */
    defalutExpandedKeys?: string[]

    /**是否不进行后端请求 */
    isNotRequest?: boolean

    /**是否不默认选中第一项可选数据 */
    isNotSelect?: boolean
}

const SearchTree: React.FC<Props> = props => {
    console.debug('SearchTree', props);

    /**treeData：树状数据 */
    const [treeData, setTreeData] = useState<TreeData[]>([]);
    /**dataList：所有树状数据放在一个数组中展示（提取 children 的内容）*/
    const [dataList, setDataList] = useState<TreeData[]>([]);
    /**expandedKeys：需要展开的树节点列表 */
    const [expandedKeys, setExpandedKeys] = useState<string[]>(props.defalutExpandedKeys || []);
    /**当前选中的节点值 */
    const [selectKeys, setSelectKeys] = useState<string[]>(props.defalutExpandedKeys || []);
    /**输入框中输入的搜索字段 */
    const [searchValue, setSearchValue] = useState('');
    /**是否展开树形结构 */
    const [autoExpandParent, setAutoExpandParent] = useState(true);

    /**根据输入内容，获取匹配到内容所对应的父级key */
    function getParentKey(key: string, tree: TreeData[]): string {
        let parentKey: any;
        for (let i = 0; i < tree.length; i++) {
            const node = tree[i];
            if (node.children) {
                if (node.children.some((item: TreeData) => item.value === key)) {
                    parentKey = node.value;
                } else if (getParentKey(key, node.children)) {
                    parentKey = getParentKey(key, node.children);
                }
            }
        }
        return parentKey;
    };

    /**生成搜索后的树状渲染数据，对应搜索字段的内容会更改样式 */
    function loop(data: any) {
        return data.map((item: TreeData) => {
            const index = item.name.indexOf(searchValue);
            const beforeStr = item.name.substr(0, index);
            const afterStr = item.name.substr(index + searchValue.length);
            const title =
                index > -1 ? (
                    <span>
                        {beforeStr}
                        <span className={styles.searchInfo}>{searchValue}</span>
                        {afterStr}
                    </span>
                ) : (
                    <span>{item.name}</span>
                );
            if (item.children) {
                return { title, key: item.value, selectable: item.selectable, children: loop(item.children) };
            }

            return { title, key: item.value, selectable: item.selectable };
        });
    }

    /**
     * 扁平化树状数据
     * @param data 树状数据
     * @returns 扁平化树状数据的数组、第一个可选数据
     */
    function flatTreeData(data: TreeData[]): [TreeData[], TreeData] {
        const list: TreeData[] = [];
        let record: any = {};
        function generateList(data: TreeData[]) {
            for (let i = 0; i < data.length; i++) {
                const node = data[i];
                const { value, name, selectable } = node;
                list.push({ value, name, selectable });
                if (node.children) {
                    generateList(node.children);
                } else {
                    if (node.selectable && _.isEmpty(record)) {
                        record = node;
                    }
                }
            }
        };
        generateList(data);
        return [list, record];
    }

    function handleChange(e: any) {
        const { value } = e.target;
        if (value) {
            const List: any[] = dataList.map(item => {
                /**筛选出含有输入内容的树状数据所对应的父级 key 值 */
                if (item.name.indexOf(value) > -1) {
                    return getParentKey(item.value, treeData);
                }
                return null;
            }).filter((item, i, self) => {
                /**筛选掉重复和为空的数据 */
                return item && self.indexOf(item) === i
            });
            if (List.length > 0) {
                setExpandedKeys(List);
                setSearchValue(value);
                setAutoExpandParent(true);
            }
        } else {
            /**搜索框内容清空时，展开之前选中项并清空选中字段样式 */
            setSearchValue('');
            setExpandedKeys(selectKeys);
        }
    };

    useEffect(() => {
        (async function () {
            if (props.remote && !props.isNotRequest) {
                const treeData: any = await props.remote();
                const [_dataList, record] = flatTreeData(treeData);
                setTreeData(treeData);
                setDataList(_dataList);
                if (!props.isNotSelect) {
                    console.log(props.isNotSelect)
                    setSelectKeys([record.value]);
                    setExpandedKeys([record.value]);
                    props.onSelect && props.onSelect(record);
                }
            }
        })()
    }, [props])

    function handleExpand(value: any) {
        setExpandedKeys(value);
        setAutoExpandParent(false);
    };

    function handleSelect(selectedKeys: any) {
        setSelectKeys(selectedKeys);
        setExpandedKeys(selectedKeys);
        setAutoExpandParent(true);
        for (let i = 0; i < dataList.length; i++) {
            const { value } = dataList[i];
            if (value === selectedKeys[0]) {
                props.onSelect && props.onSelect(dataList[i]);
                break
            }
        }
    };

    return (
        <article>
            <header className={styles.header}>
                <Search
                    placeholder={props.placeholder}
                    onChange={handleChange}
                />
            </header>
            <Tree
                onExpand={handleExpand}
                expandedKeys={expandedKeys}
                autoExpandParent={autoExpandParent}
                treeData={loop(treeData)}
                onSelect={handleSelect}
                selectedKeys={selectKeys}
            />
        </article>
    );
}

export default SearchTree;